import time

import pyautogui
import pyperclip
import xlrd


# 定义鼠标事件

# pyautogui库其他用法 https://blog.csdn.net/qingfengxd1/article/details/108270159

def mouseClick(clickTimes, lOrR, img, reTry):
    # 1代表重试一次
    if reTry == 1:
        while True:
            # 利用图片识别 识别截图在屏幕上的位置，大概只要90%（confidence）相似就认为那个位置是对的
            location = pyautogui.locateCenterOnScreen(img, confidence=0.9)
            if location is not None:
                # 移动鼠标过去并点击多次，interval两次点击之间的间隔时间，duration鼠标按键按下去保持多少时间
                pyautogui.click(location.x, location.y, clicks=clickTimes, interval=0.2, duration=0.2, button=lOrR)
                # 重试一次，成功的话这里就会brean
                break
            print("未找到匹配图片,0.1秒后重试")
            # 停一下，图片识别调用太快，CPU会很吃力
            time.sleep(0.1)
    # -1代表无限重试
    elif reTry == -1:
        while True:
            location = pyautogui.locateCenterOnScreen(img, confidence=0.9)
            if location is not None:
                pyautogui.click(location.x, location.y, clicks=clickTimes, interval=0.2, duration=0.2, button=lOrR)
            time.sleep(0.1)
    # 大于1表示需要重试多次，这个逻辑其实可以和重试1次合并，因为重试n次是同样的意思，haihua可以试着改一改
    elif reTry > 1:
        i = 1
        while i < reTry + 1:
            location = pyautogui.locateCenterOnScreen(img, confidence=0.9)
            if location is not None:
                pyautogui.click(location.x, location.y, clicks=clickTimes, interval=0.2, duration=0.2, button=lOrR)
                print("重复")
                i += 1
            time.sleep(0.1)


# 数据检查
# cmdType.value  1.0 左键单击    2.0 左键双击  3.0 右键单击  4.0 输入  5.0 等待  6.0 滚轮
# ctype     空：0
#           字符串：1
#           数字：2
#           日期：3
#           布尔：4
#           error：5
def dataCheck(sheet1):
    # 行数检查
    if sheet1.nrows < 2:
        print("没数据啊哥")
        # 我这里修改了些，直接返回，
        # 因为如果这里检测到了错误，不需要再往后检测，直接返回错误就行，最好不要浪费CPU性能
        return False
    # 每行数据检查，1代表从第二行开始
    i = 1
    # 这个循环是循环表格的每一行
    while i < sheet1.nrows:
        # 第1列 操作类型检查
        cmdType = sheet1.row(i)[0]
        if cmdType.ctype != 2 or (cmdType.value != 1.0 and cmdType.value != 2.0 and cmdType.value != 3.0
                                  and cmdType.value != 4.0 and cmdType.value != 5.0 and cmdType.value != 6.0):
            print('第', i + 1, "行,第1列数据有毛病")
            return False
        # 第2列 内容检查
        cmdValue = sheet1.row(i)[1]
        # 读图点击类型指令，内容必须为字符串类型
        if cmdType.value == 1.0 or cmdType.value == 2.0 or cmdType.value == 3.0:
            # 判断第二列的类型不为字符串
            if cmdValue.ctype != 1:
                print('第', i + 1, "行,第2列数据有毛病")
                return False
        # 输入类型，内容不能为空
        if cmdType.value == 4.0:
            if cmdValue.ctype == 0:
                print('第', i + 1, "行,第2列数据有毛病")
                return False
        # 等待类型，内容必须为数字
        if cmdType.value == 5.0:
            if cmdValue.ctype != 2:
                print('第', i + 1, "行,第2列数据有毛病")
                return False
        # 滚轮事件，内容必须为数字
        if cmdType.value == 6.0:
            if cmdValue.ctype != 2:
                print('第', i + 1, "行,第2列数据有毛病")
                return False
        # 准备到下一行
        i += 1

    # 检测过程全部征程，直接返回正值，代表正确
    return True


# 任务
def mainWork(sheet1):
    i = 1
    while i < sheet1.nrows:
        # 取本行指令的操作类型，根据不同的
        cmdType = sheet1.row(i)[0]
        # 1代表左键单击
        if cmdType.value == 1.0:
            img, reTry = getImgAndRetry(i, sheet1)
            # 鼠标点击，内部调用pyautogui
            mouseClick(1, "left", img, reTry)
            print("单击左键", img)
        # 2代表双击左键
        elif cmdType.value == 2.0:
            img, reTry = getImgAndRetry(i, sheet1)
            mouseClick(2, "left", img, reTry)
            print("双击左键", img)
        # 3代表右键
        elif cmdType.value == 3.0:
            img, reTry = getImgAndRetry(i, sheet1)
            mouseClick(1, "right", img, reTry)
            print("右键", img)
        # 4代表输入
        elif cmdType.value == 4.0:
            inputValue = sheet1.row(i)[1].value
            # 复制到系统的剪贴板，相当于对着内容 ctrl + c
            pyperclip.copy(inputValue)
            # 控制键盘，点击ctrl + v
            pyautogui.hotkey('ctrl', 'v')
            # 复制过程可能会比较慢，所以要等0.5秒
            time.sleep(0.5)
            print("输入:", inputValue)
        # 5代表等待
        elif cmdType.value == 5.0:
            # 取图片名称
            waitTime = sheet1.row(i)[1].value
            # 等待设定值
            time.sleep(waitTime)
            print("等待", waitTime, "秒")
        # 6代表滚轮
        elif cmdType.value == 6.0:
            # 取图片名称
            scroll = sheet1.row(i)[1].value
            # 向上或者向下滚动，正负代表方向
            pyautogui.scroll(int(scroll))
            print("滚轮滑动", int(scroll), "距离")
        i += 1


def getImgAndRetry(i, sheet1):
    # 取图片名称
    img = sheet1.row(i)[1].value
    # 看用户有没有定义重试次数，在表格的第三列，默认为1
    reTry = 1
    if sheet1.row(i)[2].ctype == 2 and sheet1.row(i)[2].value != 0:
        reTry = sheet1.row(i)[2].value
    # python特别的语法，会自动将两个返回值作为元组进行返回
    return img, reTry


# 主函数 从这里开始看,如果这个包被当作import的包,那么 __name__ 应该等于__package__,那么下面的函数就不会运行
if __name__ == '__main__':
    # excel文件,如果只有文件名,
    # 代表这个文件和程序在一起,
    # 可以是./cmd.xls或者是D:\\cmd.xls
    # 或者是D:/cmd.xls
    file = 'cmd.xls'
    # 打开文件,这里使用到一个叫做xlrd的工具
    wb = xlrd.open_workbook(filename=file)
    # 通过索引获取表格sheet页,这个0代表获取第一个表格，
    # 后面的表格为1、2、3、4、5、6……
    sheet1 = wb.sheet_by_index(0)
    print('欢迎使用不高兴就喝水牌RPA~')
    # 数据检查
    checkCmd = dataCheck(sheet1)
    if checkCmd:
        # 接收输入
        key = input('选择功能: 1.做一次 2.循环到死 \n')
        if key == '1':
            # 循环拿出每一行指令
            mainWork(sheet1)
        elif key == '2':
            while True:
                mainWork(sheet1)
                time.sleep(0.1)
                print("等待0.1秒")
    else:
        print('输入有误或者已经退出!')
